import datetime

from django.core.paginator import Paginator
from django.db import DatabaseError
import json
from django.core.cache import cache

from django.conf import settings
from homes.models import Area, HouseImage
from django_redis import get_redis_connection

from libs.qiniuyun.qiniu_storage import storage
from order.models import Order
from users.views import logger
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from homes.models import House,Facility
from utils import constants
from utils.decorators import login_required
from utils.param_checking import image_file
from utils.response_code import RET



class AreaListView(View):
    '''
        城区列表显示
    '''
    def get(self,request):
        area_list = cache.get('area_info')
        if area_list is None:

            areas = Area.objects.all()

            area_list = []
            for area in areas:
                area_list.append({
                    'aid':area.id,
                    'aname':area.name,

                })
        cache.set('area_info',area_list, 24 * 3600)
        return JsonResponse({'errno':RET.OK,"errmsg": "获取成功",'data':area_list})

class HousesView(View):
    def get(self, request):

        args = request.GET
        area_id = args.get('aid', '')
        start_date_str = args.get('sd', '')
        end_date_str = args.get('ed', '')
        # booking(订单量), price-inc(低到高), price-des(高到低),
        sort_key = args.get('sk', 'new')
        page = args.get('p', '1')

        try:
            page = int(page)
        except Exception as e:
            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})

        try:
            start_date = None
            end_date = None
            if start_date_str:
                start_date = datetime.datetime.strptime(start_date_str, '%Y-%m-%d')
            if end_date_str:
                end_date = datetime.datetime.strptime(end_date_str, '%Y-%m-%d')
            if start_date and end_date:
                assert start_date < end_date, Exception('开始时间大于结束时间')
        except Exception as e:

            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})

        filters = {}

        if area_id:
            filters["area_id"] = area_id

        if start_date and end_date:

            conflict_order = Order.objects.filter(begin_date__lt=end_date, end_date__gt=start_date)
        elif start_date:

            conflict_order = Order.objects.filter(end_date__gt=start_date)
        elif end_date:

            conflict_order = Order.objects.filter(begin_date__lt=end_date)
        else:
            conflict_order = []
        conflict_house_id = [order.house_id for order in conflict_order]
        if conflict_house_id:
            filters["id__in"] = conflict_house_id
        if sort_key == "booking":
            houses_query = House.objects.filter(**filters).order_by("-order_count")
        elif sort_key == "price-inc":

            houses_query = House.objects.filter(**filters).order_by("price")
        elif sort_key == "price-des":

            houses_query = House.objects.filter(**filters).order_by("-price")
        else:

            houses_query = House.objects.filter(**filters).order_by("-create_time")

        paginator = Paginator(houses_query, constants.HOUSE_LIST_PAGE_CAPACITY)

        page_houses = paginator.page(page)

        total_page = paginator.num_pages

        houses = [house.to_basic_dict() for house in page_houses]

        data = {
            "total_page": total_page,
            "houses": houses
        }
        if page <= total_page:
            try:

                redis_key = "houses_%s_%s_%s_%s" % (area_id, start_date_str, end_date_str, sort_key)
                redis_conn = get_redis_connection('house_cache')
                pl = redis_conn.pipeline()

                pl.multi()

                pl.hset(redis_key, page, json.dumps(data))

                pl.expire(redis_key, constants.HOUSE_LIST_REDIS_EXPIRES)

                pl.execute()
            except Exception as e:
                return JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数错误'})
        return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data": data})

    def post(self,request):

        user = request.user
        if user is None:
            return JsonResponse({"errno":RET.SESSIONERR, "errmsg": "用户未登录"})
        # 获取数据
        data_dict = json.loads(request.body.decode())
        title = data_dict.get('title')
        price = data_dict.get('price')
        area_id = data_dict.get('area_id')
        address = data_dict.get('address')
        room_count = data_dict.get('room_count')
        acreage = data_dict.get('acreage')
        unit = data_dict.get('unit')
        capacity = data_dict.get('capacity')
        beds = data_dict.get('beds')
        deposit = data_dict.get('deposit')
        min_days = data_dict.get('min_days')
        max_days = data_dict.get('max_days')
        facility = data_dict.get('facility')

        # 判断
        if not all([title,price,area_id,address,room_count,acreage,unit,capacity,beds,deposit,min_days,max_days,facility]):

            return JsonResponse({'erron':RET.PARAMERR,'errmsg':'参数错误'})

        try:
            price = int(float(price) * 100)
            deposit = int(float(deposit) * 100)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})

        try:
            area = Area.objects.get(id=area_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": RET.NODATA, "errmsg": "地址不存在"})

        # 保存数据
        house = House()
        house.user = user
        house.title = title
        house.price = price
        house.area = area
        house.area_id = area_id
        house.address = address
        house.room_count = room_count
        house.acreage = acreage
        house.unit = unit
        house.capacity = capacity
        house.beds = beds
        house.deposit = deposit
        house.min_days = min_days
        house.max_days = max_days

        try:
            house.save()
        except DatabaseError as e:
            logger.error(e)
            return JsonResponse({"errno": RET.DBERR, "errmsg": "数据库保存失败"})

        try:
            # 设置设施信息
            facility_id = data_dict.get('facility')
            if facility_id:
                facilities = Facility.objects.filter(id__in=facility_id)
                for facility in facilities:
                    house.facility.add(facility)
        except DatabaseError as e:
            logger.error(e)

            return JsonResponse({"errno": RET.DBERR, "errmsg": "数据库保存失败"})


        return JsonResponse({"errno": RET.OK, "errmsg": "发布成功", "data": {'house_id': house.pk}})


class HouseIndexView(View):

    def get(self, request):
        try:
            house_data = House.objects.order_by("-order_count")[0:5]
        except Exception as e:
            return JsonResponse({'errno': RET.DBERR, 'errmsg': '数据库查询失败'})
        house_list = []
        for house in house_data:
            house_list.append(house.to_basic_dict())

        return JsonResponse({'errno': RET.OK, 'errmsg': 'ok', 'data': house_list})

class UserHouseView(View):
    """
    显示用户房源信息
    """

    @method_decorator(login_required)
    def get(self, request):
        user = request.user

        house_list = []
        for house in user.houses.all():
            house_list.append(house.to_basic_dict())

        return JsonResponse({"errno": RET.OK, "errmsg": "成功", "data": {'houses': house_list}})

class HouseDetailView(View):
    """
    房屋详情页
    """
    def get(self, request, house_id):
        #获取房源信息
        try:
            house = House.objects.get(id=house_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})
        # 获取用户
        user = request.user
        #判断是否登录
        if not user.is_authenticated:
            user_id = -1
        else:
            user_id = user.id
        # 先从redis缓存中取
        redis_conn = get_redis_connection("house_cache")

        house_dict = redis_conn.get('house_info_' + house_id)
        # 如果有值,那么返回数据
        if house_dict:
            return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data":{"user_id": user_id, "house": json.loads(house_dict.decode())}})

        # 将数据缓存到redis中
        house_dict = house.to_full_dict()
        try:
            redis_conn.setex('house_info_' + house_id,  json.dumps(house_dict))
        except Exception as e:
            logger.error(e)
        # 返回数据
        return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data":{"user_id": user_id, "house": house_dict}})

class HouseImageView(View):

    def post(self,request,house_id):
        image = request.FILES.get('house_image')
        if not image:
            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})
        if not image_file(image):
            return JsonResponse({"errno": RET.PARAMERR, "errmsg": "参数错误"})
        try:
            house = House.objects.get(id=house_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": RET.NODATA, "errmsg": "该房间不存在"})

            # 读取出文件对象的二进制数据
        image_data = image.read()
        try:

            key = storage(image_data)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": RET.THIRDERR, "errmsg": "上传图片失败"})
        if not house.index_image_url:
            house.index_image_url = key
            house.save()

        house_image = HouseImage()
        house_image.house = house
        house_image.url = key
        house_image.save()


        data = {
            "url": settings.QINIU_URL + key
        }

        return JsonResponse({'errno':RET.OK,'errmsg':'图片上传成功','data':data})

